<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
  <title>基础动画</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="js/digit.js"></script>
<script>
  const CANVAS_HEIGHT = 768;
  const CANVAS_WIDTH = 1024;
  const RADIUS = 8;
  const MARGIN_TOP = 60;
  const MARGIN_LEFT = 30;
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  canvas.width = CANVAS_WIDTH;
  canvas.height = CANVAS_HEIGHT;

  const g = 2; // 模拟重力加速度
  const colors = ['#55D4E9', '#88DBE9', '#05C9E9', '#9CE905', '#BDE965', '#BF0449', '#F2B705', '#D98E04', '#F25D07', '#D90D0D']
  const balls = []

  let prev = new Date();
  requestAnimationFrame(function animate() {
    render(context);
    update(balls, context);
    requestAnimationFrame(animate);
  })


  // 只做渲染操作，不涉及位置更新操作
  function render(ctx) {
    let now = new Date();

    let hour = now.getHours();
    let minute = now.getMinutes();
    let second = now.getSeconds();

    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
    // 绘制原数字
    renderDigit(MARGIN_LEFT, MARGIN_TOP, Math.floor(hour / 10), ctx);
    renderDigit(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, Math.floor(hour % 10), ctx);
    renderDigit(MARGIN_LEFT + 30 * (RADIUS + 1), MARGIN_TOP, 10, ctx);
    renderDigit(MARGIN_LEFT + 39 * (RADIUS + 1), MARGIN_TOP, Math.floor(minute / 10), ctx);
    renderDigit(MARGIN_LEFT + 54 * (RADIUS + 1), MARGIN_TOP, Math.floor(minute % 10), ctx);
    renderDigit(MARGIN_LEFT + 69 * (RADIUS + 1), MARGIN_TOP, 10, ctx);
    renderDigit(MARGIN_LEFT + 78 * (RADIUS + 1), MARGIN_TOP, Math.floor(second / 10), ctx);
    renderDigit(MARGIN_LEFT + 93 * (RADIUS + 1), MARGIN_TOP, Math.floor(second % 10), ctx);

    // 数字变化,绘制球
    if (Math.floor(hour / 10) !== Math.floor(prev.getHours() / 10)) {
      addBalls(MARGIN_LEFT, MARGIN_TOP, Math.floor(hour / 10), ctx);
    }
    if (Math.floor(hour % 10) !== Math.floor(prev.getHours() % 10)) {
      addBalls(MARGIN_LEFT + 15 * (RADIUS + 1), MARGIN_TOP, Math.floor(hour % 10), ctx);
    }
    if (Math.floor(minute / 10) !== Math.floor(prev.getMinutes() / 10)) {
      addBalls(MARGIN_LEFT + 39 * (RADIUS + 1), MARGIN_TOP, Math.floor(minute / 10), ctx);
    }
    if (Math.floor(minute % 10) !== Math.floor(prev.getMinutes() % 10)) {
      addBalls(MARGIN_LEFT + 54 * (RADIUS + 1), MARGIN_TOP, Math.floor(minute % 10, ctx))
    }
    if (Math.floor(second / 10) !== Math.floor(prev.getSeconds() / 10)) {
      addBalls(MARGIN_LEFT + 78 * (RADIUS + 1), MARGIN_TOP, Math.floor(second / 10), ctx);
    }
    if (Math.floor(second % 10) !== Math.floor(prev.getSeconds() % 10)) {
      addBalls(MARGIN_LEFT + 93 * (RADIUS + 1), MARGIN_TOP, Math.floor(second % 10), ctx);
    }

    for (let i = 0, len = balls.length; i < len; i++) {
      const ball = balls[i];
      ctx.beginPath();
      ctx.fillStyle = ball.color;
      ctx.arc(ball.x, ball.y, RADIUS, 0, Math.PI * 2);
      ctx.closePath();
      ctx.fill();
    }

    prev = now
  }

  /**
   * 绘制数字
   * @param x{Number} 位置x
   * @param y{Number} 位置y
   * @param num{Number} 数字
   * @param ctx
   */
  function renderDigit(x, y, num, ctx) {
    ctx.fillStyle = "#797979";
    for (let i = 0, len = digit[num].length; i < len; i++) {
      for (let j = 0, len2 = digit[num][i].length; j < len2; j++) {
        if (digit[num][i][j] === 1) {
          ctx.beginPath();
          const centerX = x + (j * 2 + 1) * (RADIUS + 1);
          const centerY = y + (i * 2 + 1) * (RADIUS + 1);
          ctx.arc(centerX, centerY, RADIUS, 0, Math.PI * 2);
          ctx.closePath();
          ctx.fill()
        }
      }
    }
  }

  function addBalls(x, y, num) {
    for (let i = 0, len = digit[num].length; i < len; i++) {
      for (let j = 0, len2 = digit[num][i].length; j < len2; j++) {
        if (digit[num][i][j] === 1) {
          const centerX = x + (j * 2 + 1) * (RADIUS + 1);
          const centerY = y + (i * 2 + 1) * (RADIUS + 1);
          balls.push({
            x: centerX,
            y: centerY,
            velocityX: Math.pow(-1, Math.floor(Math.random() * 2)),  // -1或1
            velocityY: 0,
            randomG: (Math.random() * 4 + 5) * g,
            color: colors[Math.floor(Math.random() * colors.length)]
          })
        }
      }
    }
  }

  // 只做位置更新操作，不涉及render
  function update(balls) {
    for (let i = balls.length - 1; i >= 0; i--) {
      const ball = balls[i];
      ball.x += ball.velocityX;
      ball.y += ball.velocityY;
      ball.velocityY += g;
      if (ball.y + RADIUS >= CANVAS_HEIGHT) {
        ball.velocityY = -ball.velocityY;
        ball.velocityY += ball.randomG;
        ball.y = CANVAS_HEIGHT - RADIUS;
      }
      if (ball.x + RADIUS < 0 || ball.x - RADIUS > CANVAS_WIDTH) {
        balls.splice(i, 1)
      }
    }
  }
</script>
</body>
</html>
